package com.cskaoyan.javase.oop3._0abstract._0introduction;

/**
 * 抽象类的引入
 * 从以下两个角度分析：
 *      1.从代码角度上，有没有冗余代码？
 *          可以认为父类Animal类的shout方法的方法体是多余的
 *          这个方法仅仅是用来被继承和重写的,它也不需要方法体
 *
 *      2.从设计角度上，在这个案例中，会存在一个动物对象吗？
 *          没有动物这个对象
 *          动物这个类,仅仅是用来被继承的,它不需要实例化
 *
 * 综上，我们提出两个改进的方向：
 *      1.Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，于是干脆不要创建对象了。
 *          把Animal类当成一个抽象的概念来看待,不要new它的对象
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *
 * '{' or ';' expected ,补上";"
 *
 * Missing method body, or declare abstract 一个方法要么就有方法体,要么就声明为抽象
 * 抽象方法的定义:
 * [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 * 抽象方法没有方法体,没有实现,直接以";"结尾
 *
 * Abstract method in non-abstract class 抽象方法应该处在一个抽象类中
 * Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
 * 一个类要么就声明为抽象类,要么就不允许存在抽象方法
 * 总之: 抽象方法处在抽象类中,普通类中不允许出现抽象方法
 *
 * 抽象类的定义
 * [访问权限修饰符] abstract class 类名{
 *      // 类体
 * }
 *
 * 抽象类的特点,它是抽象的,不能new对象
 * 其次,抽象类也是一个类,它和它的子类之间仍然是继承的"父子"关系
 * 之前普通类的"父类引用指向子类对象"抽象类也可以是用
 * 并且多态现象照样是存在的
 *
 * @since 15:07
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated
        // new Animal();
        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

abstract class Animal {
    public abstract void shout();

    public Animal() {
        // super();
    }
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}